package com.jf3q.front.controller;

import com.alibaba.fastjson2.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jf3q.common.domain.*;
import com.jf3q.common.mapper.EduCourseMapper;
import com.jf3q.common.utils.JwtTokenUtil;
import com.jf3q.common.utils.RandomUtils;
import com.jf3q.common.vo.ResultVo;
import com.jf3q.front.service.*;
import com.jf3q.front.vo.CoursePayVo;
import com.jf3q.front.vo.CourseWebVo;
import com.jf3q.front.vo.PayObjVo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@Slf4j
public class EasyPayController {
    /**
     * TRADE_SUCCESS:   交易成功
     * TRADE_FINISHED：  交易结束，不可退款
     * TRADE_CLOSED：    超时未支付
     * WAIT_BUYER_PAY：  交易创建，等待买家付款
     */

    @Autowired
    Config config;

    @Autowired
    PayLogService payLogService;

    @Autowired
    MemberCourseService memberCourseService;

    @Autowired
    CourseDescriptionService courseDescriptionService;

    @Autowired
    OrderService orderService;

    @Autowired
    EduCourseMapper courseMapper;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    MemberService memberService;

    //订单号
    private String outTradeNo;

    //couId:课程id
    private String couId;

    //memId:会员id
    private String memId;

    //subject:订单信息
    private String subject;

    //totalAmount:金额
    private BigDecimal totalAmount;


    @PostMapping("/eduorder/order/createOrder/{courseId}")
    public ResultVo createOrder(@PathVariable String courseId) {
        Map<String, String> map = new HashMap<>();
        map.put("orderId", courseId);
        return ResultVo.success(map);
    }


    /**
     * 预创建订单
     */
    @PostMapping("/eduorder/order/getOrderInfo/{id}")
    public ResultVo getOrderInfo(@PathVariable String id, HttpServletRequest request) {

        //根据token解析出会员
        String token = request.getHeader("token");
        String name = jwtTokenUtil.getUserNameFromToken(token);
        LambdaQueryWrapper<EduMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EduMember::getMobile, name);
        EduMember member = memberService.getOne(wrapper);

        //拿到课程id
        EduCourse eduCourse = courseMapper.selectById(id);
        couId = eduCourse.getId();

        //订单信息
        subject = eduCourse.getTitle();

        //金额
        totalAmount = eduCourse.getPrice();

        //生成订单号
        String orderNo = RandomUtils.randomTwelveNum();

        //课程信息
        CourseWebVo courseWebVo = courseDescriptionService.getCourseById(id);

        CoursePayVo item = new CoursePayVo()
                .setCourseId(courseWebVo.getCourseId())
                .setCourseTitle(courseWebVo.getTitle())
                .setCourseCover(courseWebVo.getCover())
                .setTotalFee(courseWebVo.getPrice())
                .setTeacherName(courseWebVo.getTeacherName())
                .setOrderNo(orderNo);

        log.info(String.valueOf(item));

        //生成订单
        orderService.save(new EduOrder()
                .setOrderNo(orderNo)
                .setCourseId(eduCourse.getId())
                .setCourseTitle(eduCourse.getTitle())
                .setCourseCover(eduCourse.getCover())
                .setTeacherName(courseWebVo.getTeacherName())
                .setMemberId(member.getId())
                .setNickname(member.getNickname())
                .setMobile(member.getMobile())
                .setTotalFee(totalAmount)
                .setPayType((byte) 2)
                .setStatus((byte) 1));

        return ResultVo.success(item);
    }


    /**
     * 调用支付宝的扫码支付线下交易预创建接口
     * 生成付款二维码
     */
    @GetMapping("/eduorder/paylog/createNative/{orderNo}")
    public ResultVo pay(@PathVariable String orderNo, HttpServletRequest request) {

        outTradeNo = orderNo;

        //根据token解析出会员id
        String token = request.getHeader("token");
        String name = jwtTokenUtil.getUserNameFromToken(token);
        LambdaQueryWrapper<EduMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EduMember::getMobile, name);
        EduMember member = memberService.getOne(wrapper);
        memId = member.getId();

        //调用支付宝集成的方法帮助完成签名验签等工作
        Factory.setOptions(config);

        //调用支付宝接口
        //subject:订单信息  outTradeNo:订单号  totalAmount:金额
        AlipayTradePrecreateResponse response = null;
        try {
            response = Factory.Payment.FaceToFace().preCreate(subject, outTradeNo, totalAmount.toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        //解析结果                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                YIKOPJKO
        String body = response.getHttpBody();

        //转JSON对象
        JSONObject jsonObject = JSONObject.parseObject(body);
        String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();


        PayObjVo payObj = new PayObjVo();
        payObj.setOut_trade_no(outTradeNo).setTotal_fee(totalAmount.toString()).setCode_url(qrUrl).setCourse_id(couId);

        log.info("订单号=========" + outTradeNo);

        return ResultVo.success(payObj);

    }


    /**
     * 给支付宝的回调接口
     */
    @PostMapping("/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> params = new HashMap<>();
        //获取支付宝POST过来反馈信息，将异步通知中收到的待验证所有参数都存放到map中
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String name : parameterMap.keySet()) {
            String[] values = parameterMap.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //验签
        Boolean signResult = Factory.Payment.Common().verifyNotify(params);
        if (signResult) {
            log.info("收到支付宝发送的支付结果通知");
            String out_trade_no = request.getParameter("out_trade_no");
            log.info("交易订单号：{}", out_trade_no);

            String trade_no = request.getParameter("trade_no");
            log.info("交易流水号：{}", trade_no);

            //交易状态
            String tradeStatus = new String(request.getParameter("tradeStatus").getBytes("ISO-8859-1"), "UTF-8");

            //从数据库中获取订单
            LambdaQueryWrapper<EduOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EduOrder::getOrderNo, out_trade_no);

            EduOrder order = orderService.getOne(queryWrapper);

            //交易成功
            switch (tradeStatus) {
                case "TRADE_SUCCESS":
                    //支付成功的业务逻辑，比如落库，开vip权限等
                    log.info("订单：{} 交易成功", out_trade_no);
                    log.info("流水号：{} 交易成功", trade_no);
                    break;
                case "TRADE_FINISHED":
                    log.info("交易结束，不可退款");
                    //其余业务逻辑
                    break;
                case "TRADE_CLOSED":
                    log.info("超时未支付，交易已关闭，或支付完成后全额退款");
                    //其余业务逻辑
                    break;
                case "WAIT_BUYER_PAY":
                    log.info("交易创建，等待买家付款");
                    //其余业务逻辑
                    break;
            }


            //保存会员购买的课程
            if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
                memPurchased(tradeStatus, order.getId(), out_trade_no, trade_no);
            }


            response.getWriter().write("success");   //返回success给支付宝，表示消息我已收到，不用重调

        } else {
            response.getWriter().write("fail");   ///返回fail给支付宝，表示消息我没收到，请重试
        }
    }


    /**
     * 为了防止由于网路或其他原因导致支付宝没有调用/notify接口
     * 所以需要设置一个主动查询的接口去查询支付的情况
     */
    @GetMapping("/eduorder/paylog/queryPayStatus/{orderNo}")
    public ResultVo query(@PathVariable String orderNo) throws Exception {
        log.info("订单号========" + orderNo);

        //调用支付宝集成的方法帮助完成签名验签等工作
        Factory.setOptions(config);

        //调用支付宝接口根据订单编号来查询支付情况
        AlipayTradeQueryResponse query = Factory.Payment.Common().query(orderNo);

        //解析结果
        String body = query.getHttpBody();

        //转JSON对象
        JSONObject jsonObject = JSONObject.parseObject(body);

        //获取订单状态
        String tradeStatus = jsonObject.getJSONObject("alipay_trade_query_response").get("trade_status").toString();

        //获取流水号
        String tradeNo = jsonObject.getJSONObject("alipay_trade_query_response").get("trade_no").toString();
        log.info(tradeNo);


        //从数据库中获取订单
        LambdaQueryWrapper<EduOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EduOrder::getOrderNo, orderNo);
        EduOrder order = orderService.getOne(queryWrapper);


        if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
            //检查订单状态判断是否需要保存会员购买的课程
            memPurchased(tradeStatus, order.getId(), orderNo, tradeNo);
        }


        //交易成功
        switch (tradeStatus) {
            case "TRADE_SUCCESS":
                //支付成功的业务逻辑，比如落库，开vip权限等
                log.info("订单：{} 交易成功", tradeStatus);
                return ResultVo.success("交易成功");
//                break;
            case "TRADE_FINISHED":
                log.info("交易结束，不可退款");
                //其余业务逻辑
                return ResultVo.success("交易结束");
//                break;
            case "TRADE_CLOSED":
                log.info("超时未支付，交易已关闭，或支付完成后全额退款");
                //其余业务逻辑
                return ResultVo.error("超时未支付，交易已关闭，或支付完成后全额退款");
//                break;
            case "WAIT_BUYER_PAY":
                log.info("交易创建，等待买家付款");
                //其余业务逻辑
                return ResultVo.error("交易创建，等待买家付款");
//                break;
            default:
                return ResultVo.error("");
        }

    }

    /**
     * 支付完成后更新数据库
     * tradeStatus 订单状态
     * payId 订单id
     * orderNo 订单号
     * tradeNo 流水号
     */
    @Transactional
    public void memPurchased(String tradeStatus, String payId, String orderNo, String tradeNo) {
        //获取订单
        LambdaQueryWrapper<EduOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EduOrder::getOrderNo, orderNo);
        if (wrapper != null) {

            //生成订单支付记录
            payLogService.saveOrUpdate(new EduPayLog()
                    .setOrderNo(outTradeNo)
                    .setTotalFee(totalAmount)
                    .setPayType(Byte.valueOf("2"))
                    .setTradeState(tradeStatus)
                    .setTransactionId(tradeNo)
                    .setPayTime(new Date(System.currentTimeMillis()))
                    .setEduCreate(new Date(System.currentTimeMillis()))
                    .setEduModified(new Date(System.currentTimeMillis())));


            if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {

                //修改订单状态
                EduOrder eduOrder = orderService.getOne(wrapper);
                eduOrder.setStatus((byte) 1);
                orderService.saveOrUpdate(eduOrder);

                //更新课程购买数
                EduCourse eduCourse = courseMapper.selectById(couId);
                eduCourse.setBuyCount(eduCourse.getBuyCount() + 1L);
                courseMapper.updateById(eduCourse);


                LambdaQueryWrapper<EduMemberCourse> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(EduMemberCourse::getPayId, payId);

                //保存会员购买的课程
                if (memberCourseService.getOne(queryWrapper) == null) {
                    memberCourseService.save(new EduMemberCourse()
                            .setPayId(payId)
                            .setMemberId(memId)
                            .setCourseId(couId)
                            .setEduModified(new Date(System.currentTimeMillis()))
                            .setEduCreate(new Date(System.currentTimeMillis())));
                }
            }
        }

    }


}